package co.recloud.ariadne.thread;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import co.recloud.ariadne.model.Buffers;
import co.recloud.ariadne.request.DataRequest;
import co.recloud.ariadne.request.HostRequest;
import co.recloud.ariadne.request.Request;
import co.recloud.ariadne.request.TransactionRequest;
import co.recloud.ariadne.response.Response;
import co.recloud.ariadne.server.DataServer;

public class DataThread extends Thread {
	private ServerSocket serverSocket;
	private Socket socket;
	private boolean isServer;

	public DataThread(ServerSocket serverSocket) {
		this.serverSocket = serverSocket;
		isServer = true;
	}

	public DataThread(Socket socket) {
		this.socket = socket;
	}

	public void run() {
		if (isServer) {
			while (true) {
				Socket client;
				if (serverSocket.isClosed()) {
					try {
						serverSocket.bind(serverSocket.getLocalSocketAddress());
					} catch (Exception e) {
						e.printStackTrace();
						break;
					}
				}
				try {
					client = serverSocket.accept();
					ThreadPool.startDataThread(new DataThread(client));
				} catch (IOException e) {
				}
			}
		} else {
			DataServer server = new DataServer();
			ObjectInputStream in = null;
			ObjectOutputStream out = null;
			try {
				in = new ObjectInputStream(socket.getInputStream());
				out = new ObjectOutputStream(
						socket.getOutputStream());
				while(socket.isConnected()) {
                    int bufferType = in.read();
                    Request request;
                    if(bufferType == Request.SERIAL) {
					    request = (Request) in.readObject();
                    } else { //PROTOCOL BUFFER
                        request = loadRequestFromBuffer(in);
                    }
					Main.setTime(request.getTime());
					Response response = server.serve(request);
                    if(request.isResponseExpected()) {
                        out.writeObject(response);
                        out.flush();
                    }
				}
            } catch (SocketException e) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
                try {
                    out.close();
                } catch (IOException e1) {
                }
            } catch (EOFException eof) {
				try {
					in.close();
					out.close();
				} catch (Exception e) {
				}
				
			} catch (IOException e) {
			} catch (ClassNotFoundException e) {
			} finally {
				if(socket != null) {
					try {
						socket.close();
					} catch (IOException e) {
					}
				}
			}
		}
	}

    private Request loadRequestFromBuffer(ObjectInputStream in) {
        Request request = null;
        try {
            request = new DataRequest();
            int length = in.read();
            byte[] bufferData = new byte[length];
            in.read(bufferData, 0, length);
            request.loadFromMessage(Buffers.DataRequest.parseFrom(bufferData));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return request;
    }
}
